package com.library.service;

import com.library.model.Book;
import com.library.model.Reader;
import com.library.model.Borrowing;
import com.library.repository.BookRepository;
import com.library.repository.ReaderRepository;
import com.library.repository.BorrowingRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

@Service
public class BorrowingService {
    private final BorrowingRepository borrowingRepository;
    private final BookRepository bookRepository;
    private final ReaderRepository readerRepository;
    private final BookService bookService;

    @Autowired
    public BorrowingService(BorrowingRepository borrowingRepository,
                            BookRepository bookRepository,
                            ReaderRepository readerRepository,
                            BookService bookService) {
        this.borrowingRepository = borrowingRepository;
        this.bookRepository = bookRepository;
        this.readerRepository = readerRepository;
        this.bookService = bookService;
    }

    public List<Borrowing> getAllBorrowings() {
        return borrowingRepository.findAll();
    }

    public Optional<Borrowing> getBorrowingById(Long id) {
        return borrowingRepository.findById(id);
    }

    public List<Borrowing> getBorrowingsByReaderId(Long readerId) {
        return borrowingRepository.findByReaderId(readerId);
    }

    public List<Borrowing> getBorrowingsByBookId(Long bookId) {
        return borrowingRepository.findByBookId(bookId);
    }

    public List<Borrowing> getActiveBorrowings() {
        return borrowingRepository.findByReturnDateIsNull();
    }

    @Transactional
    public Borrowing borrowBook(Borrowing borrowing) {

        Book book = bookRepository.findById(borrowing.getBook().getId())
                .orElseThrow(() -> new IllegalArgumentException("Book not found"));

        Reader reader = readerRepository.findById(borrowing.getReader().getId())
                .orElseThrow(() -> new IllegalArgumentException("Reader not found"));

        if (book.getAvailableCopies() <= 0) {
            throw new IllegalStateException("No available copies for this book");
        }

        Borrowing newBorrowing = new Borrowing();
        newBorrowing.setBook(book);
        newBorrowing.setReader(reader);
        newBorrowing.setBorrowDate(borrowing.getBorrowDate());
        newBorrowing.setDueDate(borrowing.getDueDate());
        newBorrowing.setReturnDate(null);

        bookService.decreaseAvailableCopies(book.getId());

        return borrowingRepository.save(newBorrowing);
    }

    @Transactional
    public Borrowing returnBook(Long borrowingId, Borrowing borrowingDetails) {
        return borrowingRepository.findById(borrowingId)
                .map(borrowing -> {

                    if (borrowing.getReturnDate() != null) {
                        throw new IllegalStateException("This book has already been returned");
                    }

                    borrowing.setReturnDate(borrowingDetails.getReturnDate());

                    bookService.increaseAvailableCopies(borrowing.getBook().getId());

                    return borrowingRepository.save(borrowing);
                })
                .orElseThrow(() -> new IllegalArgumentException("Borrowing record not found with id: " + borrowingId));
    }


    public void deleteBorrowing(Long id) {
        borrowingRepository.deleteById(id);
    }
}
